package com.xiaodou.mjf.infrastructure.common.controller;

import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.validation.ConstraintViolationException;
import javax.validation.Validator;

import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.google.common.collect.Maps;
import com.xiaodou.mjf.infrastructure.common.components.Result;
import com.xiaodou.mjf.infrastructure.common.entity.CommonEntity;
import com.xiaodou.mjf.infrastructure.common.utils.BeanValidators;
import com.xiaodou.mjf.infrastructure.common.utils.DateUtils;
import com.xiaodou.mjf.infrastructure.common.utils.StringUtils;

public class ApplicationController {

	/**
	 * 日志对象
	 */
	protected Logger logger = LoggerFactory.getLogger(getClass());
	
	/**
	 * 验证Bean实例对象
	 */
	@Autowired
	protected Validator validator;

	/**
	 * 服务端参数有效性验证
	 * @param object 验证的实体对象
	 * @param groups 验证组
	 * @return 验证成功：返回true；严重失败：将错误信息添加到 message 中
	 */
	protected boolean beanValidator(Model model, Object object, Class<?>... groups) {
		try{
			BeanValidators.validateWithException(validator, object, groups);
		}catch(ConstraintViolationException ex){
			List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
			list.add(0, "数据验证失败：");
			addMessage(model, list.toArray(new String[]{}));
			return false;
		}
		return true;
	}
	
	/**
	 * 服务端参数有效性验证
	 * @param object 验证的实体对象
	 * @param groups 验证组
	 * @return 验证成功：返回true；严重失败：将错误信息添加到 flash message 中
	 */
	protected boolean beanValidator(RedirectAttributes redirectAttributes, Object object, Class<?>... groups) {
		try{
			BeanValidators.validateWithException(validator, object, groups);
		}catch(ConstraintViolationException ex){
			List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
			list.add(0, "数据验证失败：");
			addMessage(redirectAttributes, list.toArray(new String[]{}));
			return false;
		}
		return true;
	}
	
	/**
	 * 添加Model消息
	 * @param messages 消息
	 */
	protected void addMessage(Model model, String... messages) {
		StringBuilder sb = new StringBuilder();
		for (String message : messages){
			sb.append(message).append(messages.length>1?"<br/>":"");
		}
		model.addAttribute("message", sb.toString());
	}
	
	/**
	 * 添加Flash消息
     * @param messages 消息
	 */
	protected void addMessage(RedirectAttributes redirectAttributes, String... messages) {
		StringBuilder sb = new StringBuilder();
		for (String message : messages){
			sb.append(message).append(messages.length>1?"<br/>":"");
		}
		redirectAttributes.addFlashAttribute("message", sb.toString());
	}
	
	/**
	 * 初始化数据绑定
	 * 1. 将所有传递进来的String进行HTML编码，防止XSS攻击
	 * 2. 将字段中Date类型转换为String类型
	 */
	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		// String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
		binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
			@Override
			public void setAsText(String text) {
				setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
			}
			@Override
			public String getAsText() {
				Object value = getValue();
				return value != null ? value.toString() : "";
			}
		});
		// Date 类型转换
		binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
			@Override
			public void setAsText(String text) {
				setValue(DateUtils.parseDate(text));
			}
		});
	}

    protected Map<String,Object> page(long count,List<? extends CommonEntity> items){
        Map<String,Object> data = Maps.newHashMap();
        data.put("iTotalRecords", count);
        data.put("iTotalDisplayRecords", count);
        data.put("aaData", items);
        return data;
    }

    protected Map<String,Object> page(Page<? extends CommonEntity> page){
        Map<String,Object> data = Maps.newHashMap();
        data.put("iTotalRecords", page.getTotalElements());
        data.put("iTotalDisplayRecords", page.getTotalElements());
        data.put("aaData", page.getContent());
        return data;
    }

    protected Map<String,Object> map(boolean isSuccessful,String message){
        Map<String,Object> result = Maps.newHashMap();
        result.put("success",isSuccessful);
        result.put("message",message);
        return result;
    }

    protected Map<String,Object> map(boolean isSuccessful){
        return map(isSuccessful,StringUtils.EMPTY);
    }

    protected Map<String,Object> error(){
        return map(false,"服务器异常，请稍后重新提交.");
    }

    protected Map<String,Object> error(String message){
        return map(false,message);
    }

    protected Map<String,Object> success(){
        return map(true,StringUtils.EMPTY);
    }

    protected Map<String,Object> success(String message){
        return map(true,message);
    }

    protected Map<String,Object> map(Result result) {
        return map(result.isSuccess(),result.getMessage());
    }
}
